/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.distschedule.slice;

import com.beiing.leafchat.LeafLineChart;
import com.beiing.leafchat.bean.Axis;
import com.beiing.leafchat.bean.AxisValue;
import com.beiing.leafchat.bean.Line;
import com.beiing.leafchat.bean.PointValue;
import com.beiing.leafchat.bean.SlidingLine;
import com.example.distschedule.ResourceTable;
import com.example.distschedule.bean.DeviceResult;
import com.example.distschedule.bean.RespondBase;
import com.example.distschedule.rx2.OKHttpUtilsRx2;
import com.example.distschedule.toast.XToastUtils;
import com.example.distschedule.utils.DeviceStateUtil;
import com.example.distschedule.utils.PreferencesUtil;
import com.socks.library.KLog;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbPalette;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.utils.Color;
import ohos.ai.tts.TtsClient;
import ohos.ai.tts.TtsListener;
import ohos.ai.tts.TtsParams;
import ohos.ai.tts.constants.TtsEvent;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.miscservices.timeutility.Time;
import ohos.utils.PacMap;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import static com.example.distschedule.utils.CommonUtil.getRateStr;


/**
 * 体重秤控制页面
 */
public class ElectronicScaleAbilitySlice extends AbilitySlice {
    private String deviceId;

    private Text scaleSatet;

    private Text currentHeightValue;
    private Text currentWeightValue;
    private Text BMI;

    LeafLineChart leafLineChart;

    private Image readImg;
    private boolean initItsResult;

    private static final int EVENT_MSG_INIT = 0x1000001;
    private static final int EVENT_MSG_TIME_COUNT = 0x1000002;

    private Timer timer = null;
    private TimerTask timerTask = null;

    private Timer getDeviceTimer = null;
    private TimerTask getDeviceTimerTask = null;

    List<Float> weightRecord = new ArrayList<>();

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);

        super.setUIContent(ResourceTable.Layout_ability_electronic_scale);

        deviceId = intent.getStringParam("deviceId");

        initComponents();
        initTtsEngine();

        if (getDeviceTimer == null && getDeviceTimerTask == null) {
            getDeviceTimer = new Timer();
            getDeviceTimerTask = new TimerTask() {
                public void run() {
                    handler.sendEvent(EVENT_MSG_INIT);
                }
            };
            getDeviceTimer.schedule(getDeviceTimerTask, 0, 1000);
        }
    }

    private void initElectronicScaleState() {
        TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
        globalTaskDispatcher.asyncDispatch(() -> {
            KLog.i("async task initLampState run");
            checkDeviceNet();
        });
    }

    private void initDeviceState() {
        OKHttpUtilsRx2.INSTANCE.getApi().getDeviceInfo(deviceId, PreferencesUtil.getUserId(getContext()))
                .compose(OKHttpUtilsRx2.INSTANCE.ioMain())
                .subscribe(new OKHttpUtilsRx2.SubjectImpl<RespondBase<DeviceResult>>() {
                    @Override
                    public void onNext(RespondBase<DeviceResult> deviceInfo) {
                        KLog.i(deviceInfo);
                        if (deviceInfo.isSuccess() && deviceInfo.getResult().isOnline()) {
                            // 更新状态
                            updateDeviceState(deviceInfo);

                        } else {
                            initElectronicScaleState();
                        }
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        initElectronicScaleState();
                    }
                });
    }

    private void updateDeviceState(RespondBase<DeviceResult> deviceInfo) {
        String property = deviceInfo.getResult().getProperty();
        String heightValue = DeviceStateUtil.getKeyValue(property, "height");
        String weightValue = DeviceStateUtil.getKeyValue(property, "weight");
        if (currentWeightValue.getText().matches(weightValue) && currentHeightValue.getText().matches(heightValue)) {
            KLog.i("身高体重都没有变化");
        } else {
            float tempHeight = Float.parseFloat(heightValue);
            float tempWeight = Float.parseFloat(weightValue);
            // 体重有变化再增加，只显示最近7天的数据
            if (!(currentWeightValue.getText().matches(weightValue))) {

                currentWeightValue.setText(weightValue);

                weightRecord.add(tempWeight);
                if (weightRecord.size() == 8) {
                    weightRecord.remove(0);
                }
                initChart(weightRecord);
            }
            currentHeightValue.setText(heightValue);
            getBmi(tempHeight, tempWeight);
        }
    }

    private void getBmi(Float tempHeight, Float tempWeight) {
        float tempBmi;
        if (tempHeight == 0.00) {
            tempBmi = 0;
        } else {
            tempBmi = tempWeight / (tempHeight * tempHeight);
            if (tempBmi > 23.9) {
                scaleSatet.setText("体重偏胖");
                scaleSatet.setTextColor(new Color(Color.rgb(232, 64, 38)));
            }
            if (tempBmi < 18.5) {
                scaleSatet.setText("体重偏瘦");
                scaleSatet.setTextColor(new Color(Color.rgb(237, 111, 33)));
            }
        }
        BMI.setText(getRateStr(Float.toString(tempBmi))); // BMI 是 体重除以身高平方 体重单位为kg,身高单位为 米
    }

    private void checkDeviceNet() {
        Time.sleep(10 * 1000);
        OKHttpUtilsRx2.INSTANCE.getApi().getDeviceInfo(deviceId, PreferencesUtil.getUserId(getContext()))
                .compose(OKHttpUtilsRx2.INSTANCE.ioMain())
                .subscribe(new OKHttpUtilsRx2.SubjectImpl<RespondBase<DeviceResult>>() {
                    @Override
                    public void onNext(RespondBase<DeviceResult> deviceInfo) {
                        super.onNext(deviceInfo);
                        KLog.i(deviceInfo);
                        if (deviceInfo.getResult() == null || !deviceInfo.getResult().isOnline()) {
                            XToastUtils.toast("未配网成功，请再次碰一碰重试");
                        }
                    }
                });
    }

    private void initComponents() {

        scaleSatet = (Text) findComponentById(ResourceTable.Id_scale_text_switch);

        findComponentById(ResourceTable.Id_scale_img_left).setClickedListener(this::goBack);
        findComponentById(ResourceTable.Id_scale_img_right).setClickedListener(this::goInfo);
        currentHeightValue = (Text) findComponentById(ResourceTable.Id_scale_text_height);
        currentWeightValue = (Text) findComponentById(ResourceTable.Id_scale_text_weight);
        BMI = (Text) findComponentById(ResourceTable.Id_scale_text_bmi);

        readImg = (Image) findComponentById(ResourceTable.Id_scale_image_voice);
        readImg.setClickedListener(this::readText);
        weightRecord.add(Float.parseFloat(currentWeightValue.getText()));
        initChart(weightRecord);
    }

    private void initChart(List<Float> weightRecord) {
        leafLineChart = (LeafLineChart) findComponentById(ResourceTable.Id_leaf_chart);

        SlidingLine slidingLine = new SlidingLine();
        slidingLine.setOpenSlideSelect(true);

        Axis axisX = new Axis(getAxisValuesX());
        axisX.setAxisColor(RgbPalette.parse("#007DFF")).setTextColor(Color.DKGRAY.getValue()).setHasLines(true);
        Axis axisY = new Axis(getAxisValuesY());
        axisY.setAxisColor(RgbPalette.parse("#007DFF")).setTextColor(Color.DKGRAY.getValue()).setHasLines(true).setShowText(true);
        leafLineChart.setAxisX(axisX);
        leafLineChart.setAxisY(axisY);

        List<Line> lines = new ArrayList<>();
        lines.add(getFoldLine(weightRecord));
        leafLineChart.setChartData(lines);
        leafLineChart.show();
    }

    private List<AxisValue> getAxisValuesX() {
        List<AxisValue> axisValues = new ArrayList<>();
        for (int i = 1; i <= 7; i++) {
            AxisValue value = new AxisValue();
            value.setLabel("第" + i + "天");
            axisValues.add(value);
        }
        return axisValues;
    }

    private List<AxisValue> getAxisValuesY() {
        List<AxisValue> axisValues = new ArrayList<>();
        for (int i = 0; i < 11; i++) {
            AxisValue value = new AxisValue();
            value.setLabel(String.valueOf(i * 10));
            axisValues.add(value);
        }
        return axisValues;
    }

    private Line getFoldLine(List<Float> weightRecord) {
        List<PointValue> pointValues = new ArrayList<>();

        for (int i = 0; i < weightRecord.size(); i++) {
            PointValue pointValue = new PointValue();
            pointValue.setX((i) / 6f);
            float var = weightRecord.get(i);
            pointValue.setLabel(String.valueOf(var));
            pointValue.setY(var / 100f);
            pointValues.add(pointValue);
        }


        Line line = new Line(pointValues);
        line.setLineColor(RgbPalette.parse("#007DFF"))
                .setLineWidth(3)
                .setPointColor(Color.YELLOW.getValue())
                .setCubic(false)
                .setPointRadius(3)
                .setFill(true)
                .setFillColor(RgbPalette.parse("#007DFF"))
                .setHasLabels(true)
                .setLabelColor(RgbPalette.parse("#007DFF"));
        return line;
    }

    private void goBack(Component component) {
        onBackPressed();
    }

    private void goInfo(Component component) {
        XToastUtils.info("实时读取身高体重，计算BMI，绘制体重曲线");
    }

    private final EventHandler handler = new EventHandler(EventRunner.current()) {
        @Override
        protected void processEvent(InnerEvent event) {
            switch (event.eventId) {
                case EVENT_MSG_TIME_COUNT:
                    getUITaskDispatcher().delayDispatch(() -> readImg.setPixelMap(ResourceTable.Media_icon_voice_unselected), 0);
                    break;
                case EVENT_MSG_INIT:
                    getUITaskDispatcher().delayDispatch(() -> {
                        initDeviceState();
                        KLog.i("...initDeviceState====");
                    }, 0);
                    break;
                default:
                    break;
            }
        }
    };

    private void initTtsEngine() {
        TtsClient.getInstance().create(this, ttsListener);
    }

    private void readText(Component component) {
        readImg.setPixelMap(ResourceTable.Media_icon_voice_selected);
        if (initItsResult) {
            KLog.i("...initItsResult is true, speakText");
            TtsClient.getInstance().speakText("身高" + currentHeightValue.getText() + "米" + "体重" + currentWeightValue.getText() + "千克", null);
        } else {
            KLog.e("...initItsResult is false");
        }
    }

    private final TtsListener ttsListener = new TtsListener() {
        @Override
        public void onEvent(int eventType, PacMap pacMap) {
            KLog.i("...onEvent...");
            // 定义TTS客户端创建成功的回调函数
            if (eventType == TtsEvent.CREATE_TTS_CLIENT_SUCCESS) {
                TtsParams ttsParams = new TtsParams();
                ttsParams.setDeviceId(UUID.randomUUID().toString());
                initItsResult = TtsClient.getInstance().init(ttsParams);
            }
        }

        @Override
        public void onStart(String utteranceId) {
            KLog.i("...onStart...");
        }

        @Override
        public void onProgress(String utteranceId, byte[] audioData, int progress) {
        }

        @Override
        public void onFinish(String utteranceId) {
            KLog.i("...onFinish...");
        }

        @Override
        public void onError(String s, String s1) {
            KLog.i("...onError...");
        }

        @Override
        public void onSpeechStart(String utteranceId) {
            // 开始计时
            KLog.i("...onSpeechStart...");

        }

        @Override
        public void onSpeechProgressChanged(String utteranceId, int progress) {
        }

        @Override
        public void onSpeechFinish(String utteranceId) {
            // 结束计时
            KLog.i("...onSpeechFinish...");
            if (timer == null && timerTask == null) {
                timer = new Timer();
                timerTask = new TimerTask() {
                    public void run() {
                        handler.sendEvent(EVENT_MSG_TIME_COUNT);
                    }
                };
                timer.schedule(timerTask, 0, 1000);
            }
        }
    };

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
        timer.cancel();
        timer = null;
        timerTask = null;
        getDeviceTimer.cancel();
        getDeviceTimer = null;
        getDeviceTimerTask = null;
    }
}

